package com.dyna.foundation.convert;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.dyna.core.utils.StringUtil;
import com.dyna.enums.MenuTypeEnum;
import com.dyna.foundation.domain.bo.UserInfoBo;
import com.dyna.foundation.domain.bo.po.SysRolePo;
import com.dyna.foundation.domain.entity.SysMenu;
import com.dyna.foundation.domain.resp.SysPermissionInfoResp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

import static com.dyna.core.utils.CollUtil.filterList;
import static com.dyna.foundation.domain.entity.SysMenu.ID_ROOT;

public class AuthPermissionConvert {

    private static final Logger logger = LoggerFactory.getLogger(AuthPermissionConvert.class);

    public static SysPermissionInfoResp convert(UserInfoBo userInfoBo, List<SysMenu> menuList) {
        Set<String> roles = userInfoBo.getRoleList().stream().map(SysRolePo::getCode).collect(Collectors.toSet());
        Set<String> permissions = menuList.stream().map(SysMenu::getPermission).filter(StringUtil::isNoneBlank).collect(Collectors.toSet());
        SysPermissionInfoResp sysPermissionInfoResp = SysPermissionInfoResp.builder()
                .user(BeanUtil.copyProperties(userInfoBo, SysPermissionInfoResp.UserVO.class))
                .roles(roles)
                .permissions(permissions)
                .menus(buildMenuTree(menuList))
                .build();
        return sysPermissionInfoResp;
    }

    /**
     * 将菜单列表，构建成菜单树
     *
     * @param menuList 菜单列表
     * @return 菜单树
     */
    public static List<SysPermissionInfoResp.MenuVO> buildMenuTree(List<SysMenu> menuList) {
        if (CollUtil.isEmpty(menuList)) {
            return Collections.emptyList();
        }
        // 移除按钮
        menuList.removeIf(menu -> menu.getType().equals(MenuTypeEnum.BUTTON.getValue()));
        // 排序，保证菜单的有序性
        menuList.sort(Comparator.comparing(SysMenu::getSort));

        // 构建菜单树
        // 使用 LinkedHashMap 的原因，是为了排序 。实际也可以用 Stream API ，就是太丑了。
        Map<Long, SysPermissionInfoResp.MenuVO> treeNodeMap = new LinkedHashMap<>();
        menuList.forEach(menu -> treeNodeMap.put(menu.getId(), BeanUtil.copyProperties(menu, SysPermissionInfoResp.MenuVO.class)));
        // 处理父子关系
        treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(ID_ROOT)).forEach(childNode -> {
            // 获得父节点
            SysPermissionInfoResp.MenuVO parentNode = treeNodeMap.get(childNode.getParentId());
            if (parentNode == null) {
                logger.info("[buildRouterTree][resource({}) 找不到父资源({})]", childNode.getId(), childNode.getParentId());
                return;
            }
            // 将自己添加到父节点中
            if (parentNode.getChildren() == null) {
                parentNode.setChildren(new ArrayList<>());
            }
            parentNode.getChildren().add(childNode);
        });
        // 获得到所有的根节点
        return filterList(treeNodeMap.values(), node -> ID_ROOT.equals(node.getParentId()));
    }

}
